//////////////////////////////////////////
//
//	FlexInc. 2010
//	http://www.loziosecchi.it/flex_inc
//	http://twitter.com/loziosecchi
//
//////////////////////////////////////////

package flexInc.spark.components.supportClasses
{
	import flash.display.BitmapData;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import mx.collections.IList;
	import mx.events.FlexEvent;
	
	import spark.components.Group;
	import spark.components.Image;
	import spark.components.SkinnableContainer;
	
	//--------------------------------------
	//  Skin states
	//--------------------------------------
	
	/**
	 *  Up State of the Button
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion Flex 4
	 */
	[SkinState("normal")]
	
	/**
	 *  Over State of the Button
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion Flex 4
	 */
	[SkinState("disabled")]
	
	/**
	 *  The ImageRotatorBase class is the base class for the all Spark image rotator components.
	 *  The ImageRotator class is a subclass of ImageRotatorBase.
	 * 
	 *  @see flexInc.spark.components.ImageRotator
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10
	 *  @playerversion AIR 1.5
	 *  @productversion Flex 4
	 */
	public class ImageRotatorBase extends SkinnableContainer
	{
		/**
		 * A pointer to the selected element in the list. If a value of -1 is set,
		 * it means no item is selected.
		 */
		protected var _selectedIndex:int = -1;
		
		/**
		 * The timer used for the slide interval
		 */
		protected var _timer:Timer;
		
		/**
		 *  The first image used for visualization and image swapping. 
		 */
		protected var _image0:Image;
		
		/**
		 *  The second image used for visualization and image swapping. 
		 */
		protected var _image1:Image;
		
		/**
		 * Constructor
		 */
		public function ImageRotatorBase()
		{
			super();
			
			initializeTimer();
			
			addHandlers();
		}
		
		//----------------------------------
		//  public functions
		//----------------------------------
		
		/**
		 * Sets the next element in the list
		 */
		public function setNextElement():void
		{
			var index:uint = _selectedIndex;
			
			if(_selectedIndex < imagesList.length - 1)
				index = _selectedIndex + 1;
			else
				index = 0;
			
			selectedIndex = index;
		}
		
		/**
		 * Sets the next previous in the list
		 */
		public function setPreviousElement():void
		{
			var index:uint = _selectedIndex;
			
			if(_selectedIndex > 0)
				index = _selectedIndex - 1;
			else
				index = imagesList.length - 1;
			
			selectedIndex = index;
		}
		
		//--------------------------------------------------------------------------
		//
		//  protected functions
		//
		//--------------------------------------------------------------------------
		
		/**
		 * @private
		 */
		protected function addHandlers():void
		{			
			addEventListener(FlexEvent.DATA_CHANGE, onDataChange);
		}
		
		/**
		 *  Initializes the timer used to set the time beetween transitions.
		 */
		protected function initializeTimer():void
		{
			_timer = new Timer(5000);
			_timer.addEventListener(TimerEvent.TIMER, onTimer);			
		}
		
		/**
		 *  @private
		 */
		override protected function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);
			
			if(instance == imageContainer)
			{
				_image0 = imageContainer.image0;
				_image0.source = new BitmapData(1, 1, true, 0x00000000); // create a 1x1 pixel bitmap or the first transition won't work
				_image0.addEventListener(Event.COMPLETE, onImageLoadComplete, false, 0, true);
				
				_image1 = imageContainer.image1;
				_image1.source = new BitmapData(1, 1, true, 0x00000000); // create a 1x1 pixel empty bitmap or the first transition won't work
				_image1.addEventListener(Event.COMPLETE, onImageLoadComplete, false, 0, true);
				_image1.visible = false;
			}
		}
		
		/**
		 *  @private
		 */
		override protected function partRemoved(partName:String, instance:Object):void
		{
			super.partRemoved(partName, instance);
			
			if(instance == imageContainer)
			{
				_image0.removeEventListener(Event.COMPLETE, onImageLoadComplete);
				
				_image1.removeEventListener(Event.COMPLETE, onImageLoadComplete);
			}
		}
		
		/**
		 * When an image has been loaded, play the corresponding transition
		 * 
		 * @param event
		 */
		protected function onImageLoadComplete(event:Event):void
		{
			playTransition();
		}
		
		/**
		 * Plays the transition for the new image and starts the
		 * slide timer
		 */
		protected function playTransition():void
		{
			imageContainer.currentState = (imageContainer.currentState == "flipped") ? "normal" : "flipped";
			
			_timer.start();
		}
		
		/**
		 * When data changes, starts a new slide show process
		 * 
		 * @param event
		 */
		protected function onDataChange(event:FlexEvent = null):void
		{
			selectedIndex = 0;
		}
		
		/**
		 * @private
		 */
		protected function onTimer(event:TimerEvent):void
		{
			setNextElement();
		}
		
		/**
		 * Loads the newly selected image
		 */
		protected function loadImage():void
		{
			if(imageContainer)
			{
				var image:Image = _image0.visible ? _image1 : _image0;
				if(image.source != String(selectedItem.image_url))
					image.source = String(selectedItem.image_url);
				else
					playTransition();
			}
		}
		
		/**
		 *  @private
		 */
		override protected function getCurrentSkinState():String
		{
			if (!enabled)
				return "disabled";
			
			return "normal";
		}
		
		//--------------------------------------------------------------------------
		//
		//  getters and setters
		//
		//--------------------------------------------------------------------------
		
		/**
		 * Returns the selected item in the list
		 */
		protected function get selectedItem():Object
		{
			return imagesList.getItemAt(_selectedIndex);
		}
		
		/**
		 * The index for the selected item in the list
		 */
		public function get selectedIndex():uint
		{
			return _selectedIndex;
		}
		
		/**
		 *  @private
		 */
		public function set selectedIndex(value:uint):void
		{
			if(!(value >= 0 && value < imagesList.length))
				throw new IllegalOperationError("Selected index is out of bounds.");
			
			_timer.stop();
			_selectedIndex = value;
			
			loadImage();
		}
		
		/**
		 * This is the delay used for the time counter
		 */
		public function get slideTimerDelay():uint
		{
			return _timer.delay;
		}
		
		/**
		 *  @private
		 */
		public function set slideTimerDelay(value:uint):void
		{
			_timer.delay = value;
		}
		
		//----------------------------------
		//  data
		//----------------------------------
		
		/**
		 *  @private
		 *  Storage for the imagesList property.
		 */
		private var _imagesList:IList;
		
		[Bindable("dataChange")]
		
		public function get imagesList():IList
		{
			return _imagesList;
		}
		
		/**
		 *  @private
		 */
		public function set imagesList(value:IList):void
		{
			_imagesList = value;
			
			dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
		}
		
		//--------------------------------------------------------------------------
		//
		//  skin parts
		//
		//--------------------------------------------------------------------------
		
		[SkinPart(required="true")]
		/**
		 *  A skin part that defines the image container. 
		 */
		public var imageContainer:ImageRotatorImageContainer;
	}
}